#pragma once
#include "stdafx.h"
# include <deque>
# include <stack>
# include <string>
# include <iostream>
# include "BSValue.h"

class BSReader
{

public:
	typedef char Char;
	typedef const Char *Location;
	typedef std::stack<BSValue *> Nodes;

	/** \brief Constructs a Reader allowing all features
	* for parsing.
	*/
	BSReader();

	~BSReader();

	/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
	* \param document UTF-8 encoded string containing the document to read.
	* \param root [out] Contains the root value of the document if it was
	*             successfully parsed.
	* \return \c true if the document was successfully parsed, \c false if an error occurred.
	*/
	bool parse( const std::string &document,  BSValue &root);

	/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
	* \param document UTF-8 encoded string containing the document to read.
	* \param root [out] Contains the root value of the document if it was
	*             successfully parsed.
	* \return \c true if the document was successfully parsed, \c false if an error occurred.
	*/
	bool parse( const char *beginDoc, const char *endDoc,   BSValue &root  );

	/// \brief Parse from input stream.
	/// \see Json::operator>>(std::istream&, Json::Value&).
	bool parse( std::istream &is,BSValue &root );

private:
	enum TokenType
	{
		tokenEndOfStream = 0,
		tokenObjectBegin,
		tokenObjectEnd,
		tokenArrayBegin,
		tokenArrayEnd,
		tokenString,
		tokenNumber,
		tokenTrue,
		tokenFalse,
		tokenNull,
		tokenArraySeparator,
		tokenMemberSeparator
	};

	class Token
	{
	public:
		TokenType type_;
		Location start_;
		Location end_;
	};
private:
	bool expectToken( TokenType type, Token &token, const char *message );
	bool readToken( Token &token );
	void skipSpaces();
	bool match( Location pattern, int patternLength );
	bool readString();
	void readNumber();
	bool readValue();
	bool readObject( Token &token );
	bool readArray( Token &token );
	bool decodeNumber( Token &token );
	bool decodeString( Token &token );
	bool decodeString( Token &token, std::string &decoded );
	bool decodeDouble( Token &token );
	bool decodeUnicodeCodePoint( Token &token, 
		Location &current, 
		Location end, 
		unsigned int &unicode );
	bool decodeUnicodeEscapeSequence( Token &token, 
		Location &current, 
		Location end, 
		unsigned int &unicode );
	void skipUntilSpace();
	BSValue &currentValue();
	Char getNextChar();
	void getLocationLineAndColumn( Location location,
		int &line,
		int &column ) const;
	std::string getLocationLineAndColumn( Location location ) const;
	

private:
	Nodes nodes_;
	std::string document_;
	Location begin_;
	Location end_;
	Location current_;
	Location lastValueEnd_;
	BSValue *lastValue_;
	std::string commentsBefore_;
	bool collectComments_;
};

